package org.hilo.boot.core;

import java.util.Map;
import java.util.Properties;

import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotationMetadata;

import tk.mybatis.mapper.common.Marker;
import tk.mybatis.mapper.mapperhelper.MapperHelper;
import tk.mybatis.mapper.util.StringUtil;

/**
 * 
 * @author zollty
 * @since 2016-10-21
 */
public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware {
    private Logger logger = LoggerFactory.getLogger(MapperScannerRegistrar.class);
    private final MapperHelper mapperHelper = new MapperHelper();

    /**
     * 注册完成后，对MapperFactoryBean的类进行特殊处理
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, 
            BeanDefinitionRegistry registry) {
        
        AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(
                importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));
        Class<?> markerInterface = annoAttrs.getClass("markerInterface");
        if (Marker.class.isAssignableFrom(markerInterface)) {
            mapperHelper.registerMapper(markerInterface);
        }
        Properties props = new Properties();
        Map<String, Object> map = binder.bind("mybatis.properties", Bindable.mapOf(String.class, Object.class)).get();
        if (map != null) {
            props.putAll(map);
            mapperHelper.setProperties(props);
        }
        
        annoAttrs = AnnotationAttributes.fromMap(
                importingClassMetadata.getAnnotationAttributes(MapperScanExt.class.getName()));
        if (annoAttrs != null) {
            Class<?>[] markerInterfaces = annoAttrs.getClassArray("value");
            if(markerInterfaces.length==0) {
                markerInterfaces = annoAttrs.getClassArray("markerInterface");
            }
            for(Class<?> marker: markerInterfaces) {
                if (Marker.class.isAssignableFrom(marker)) {
                    logger.info("set scan {} ......", marker);
                    mapperHelper.registerMapper(marker);
                }
            }
        }

        // 如果没有注册过接口，就注册默认的Mapper接口
        //this.mapperHelper.ifEmptyRegisterDefaultInterface();
        String[] names = registry.getBeanDefinitionNames();
        GenericBeanDefinition definition;
        for (String name : names) {
            BeanDefinition beanDefinition = registry.getBeanDefinition(name);
            if (beanDefinition instanceof GenericBeanDefinition) {
                definition = (GenericBeanDefinition) beanDefinition;
                if (StringUtil.isNotEmpty(definition.getBeanClassName())
                        && definition.getBeanClassName().equals("org.mybatis.spring.mapper.MapperFactoryBean")) {
                    logger.debug("Processing mapper {}......", name);
                    definition.setBeanClass(tk.mybatis.spring.mapper.MapperFactoryBean.class);
                    definition.getPropertyValues().add("mapperHelper", this.mapperHelper);
                }
            }
        }
    }

    private Binder binder;
    @Override
    public void setEnvironment(Environment environment) {
        binder = Binder.get(environment);
    }
}
